﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SlimDX;

namespace Gype.GUI.Components
{
    public class ContactList : Component
    {
        public ContactList()
        {
            //mScrollOffset = new Random().Next(0, 1200);
        }

        public void AddContact(SKYPE4COMLib.User contact)
        {
            AddContact(new ContactEntry(contact));
        }

        internal override void RenderObject()
        {
            mGUIManager.Target.DrawRectangle(new Vector2(Location.X - 3, Location.Y + 3), new Vector2(Size.Width + 6, Size.Height - 8), BrushCollection.TabHeaderItemBorderSelect, 1,
                UI.RectangleFillMask.Top);

            mGUIManager.Target.PushClipArea(new System.Drawing.RectangleF(Location.X + 3, Location.Y + 5, Size.Width, Size.Height - 4));

            Vector2 start = new Vector2(Location.X + 3, Location.Y + 8 - (mScrollOffset *  ((mContacts.Count - (int)mNumItemsShown) * 26) / (Size.Height - 16)));
            foreach (var contact in mContacts)
            {
                if (start.Y + contact.Size.Height + 20 < Location.Y + 5)
                {
                    start.Y += contact.Size.Height + 6;
                    continue;
                }

                if (contact == mCurHover)
                    mHoverPosition = start;

                contact.RenderObject(start);

                start.Y += contact.Size.Height + 6;

                if (start.Y >= Size.Height)
                    break;
            }

            if (mRenderScrollBar)
            {
                mGUIManager.Target.FillRoundedRectangle(new Vector2(Location.X + Size.Width - 11, Location.Y + 8 + mScrollOffset), new Vector2(8, mScrollLength), 3, 3, BrushCollection.ContactListScroll);
            }

            mGUIManager.Target.PopClipArea();
        }

        internal override void RenderTopLevel()
        {
            if (mCurHover != null)
                mCurHover.DrawTopLevel(mHoverPosition);
        }

        internal override void AttachedToManager(Manager mgr)
        {
            base.AttachedToManager(mgr);
        }

        internal override void OnMessage(ControlMessage message)
        {
            if (message is MouseMessage)
            {
                MouseMessage msg = message as MouseMessage;
                switch (msg.Message)
                {
                    case Win32Native.WM.MOUSEMOVE:
                        {
                            if (mIsScrollbarPressed == true)
                            {
                                float dy = msg.Y - mLastScrollBarClick.Y;
                                if (mScrollOffset + dy < 0)
                                    mScrollOffset = 0;
                                else if (mScrollOffset + dy > (Size.Height - 16 - mScrollLength))
                                    mScrollOffset = (int)(Size.Height - 16 - mScrollLength);
                                else
                                {
                                    mScrollOffset += (int)dy;
                                    mLastScrollBarClick = new Vector2(msg.X, msg.Y);
                                }

                                break;
                            }

                            ContactEntry hover = ContactFromPoint(msg.X, msg.Y);
                            if (mCurHover != null && hover != mCurHover)
                                mCurHover.IsHovered = false;

                            if (hover != null)
                                hover.IsHovered = true;

                            mCurHover = hover;
                        }
                        break;

                    case Win32Native.WM.LBUTTONDOWN:
                        {
                            float scrollBarX = Location.X + Size.Width - 15;
                            float scrollBarY = Location.Y + 8 + mScrollOffset;
                            if (msg.X >= scrollBarX && (msg.X - scrollBarX) <= 10 && msg.Y >= scrollBarY && (msg.Y - scrollBarY) <= mScrollLength)
                            {
                                mIsScrollbarPressed = true;
                                mLastScrollBarClick = new Vector2(msg.X, msg.Y);
                                break;
                            }

                            mIsScrollbarPressed = false;
                        }
                        break;

                    case Win32Native.WM.LBUTTONUP:
                        {
                            mIsScrollbarPressed = false;
                        }
                        break;
                }
            }
        }

        internal void recalcContactList()
        {
            float totalY = 5 + mContacts.Count * 26;
            bool newState = totalY > Size.Height;
            if (mRenderScrollBar != newState)
            {
                foreach (var contact in mContacts)
                    contact.Size = new System.Drawing.SizeF(Size.Width - (newState ? 20 : 6), 20);
            }

            mRenderScrollBar = newState;

            if (newState)
            {
                mNumItemsShown = (Size.Width - 5) / 26.0f;
                float pctShown = mNumItemsShown / mContacts.Count;
                mScrollLength = pctShown * (Size.Width - 5);
            }
        }

        internal ContactEntry ContactFromPoint(int x, int y)
        {
            if (y < 3 || y > Size.Height)
                return null;

            float Y = Location.Y + 8 - (mScrollOffset *  ((mContacts.Count - (int)mNumItemsShown) * 26) / (Size.Height - 16));
            foreach (var contact in mContacts)
            {
                if (x >= 3 && x <= (3 + contact.Size.Width) &&
                    y >= Y && y <= (Y + contact.Size.Height + 2))
                {
                    return contact;
                }

                Y += contact.Size.Height + 6;
            }

            return null;
        }

        public void AddContact(ContactEntry contact)
        {
            float Y = 5 + mContacts.Count * 26;
            contact.Location = new System.Drawing.PointF(3, Y);
            contact.Size = new System.Drawing.SizeF(Size.Width - 6, 20);

            contact.AttachedToManager(mGUIManager);
            mContacts.Add(contact);
            mContacts.Sort((c1, c2) =>
                {
                    if ((int)c1.OnlineStatus > (int)c2.OnlineStatus)
                        return -1;
                    if ((int)c1.OnlineStatus == (int)c2.OnlineStatus)
                        return string.Compare(c1.ContactName, c2.ContactName);
                    else
                        return 1;
                }
            );

            recalcContactList();
            if (mRenderScrollBar == true)
                contact.Size = new System.Drawing.SizeF(Size.Width - 20, 20);
        }

        private Vector2 mLastScrollBarClick = new Vector2(0, 0);
        private bool mIsScrollbarPressed = false;
        private float mNumItemsShown = 1;
        private float mScrollLength = 20;
        private bool mRenderScrollBar = false;
        private List<ContactEntry> mContacts = new List<ContactEntry>();
        private ContactEntry mCurHover = null;
        private Vector2 mHoverPosition = Vector2.Zero;
        private int mScrollOffset = 0;
    }
}
